package com.mazegame.test;

import java.util.*;
import javax.swing.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
import javax.media.j3d.*;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.Timer;


public class MazePlot3 extends Applet {

    //1.迷宫总类的属性成员与构造方法
    private boolean isAlive = true; // 是否存活

    //伤害冷却相关
    private long lastHitTime = 0; // 记录上次碰撞时间
    private static final long HIT_COOLDOWN = 1000; // 碰撞冷却时间（1000ms = 1秒）
    private boolean isInvincible = false; // 是否处于无敌状态
    private long invincibilityEndTime = 0; // 无敌状态结束时间
    private int flashCounter = 0; // 闪烁计数器
    private static final int FLASH_DURATION = 5; // 闪烁持续时间（秒）
    private static final int FLASH_INTERVAL = 100; // 闪烁间隔（毫秒）
    private static final int FLASH_COUNT = (int)(FLASH_DURATION * 1000 / FLASH_INTERVAL); // 闪烁次数


    // 道具相关
    private static final int WALL_PASS_DURATION = 10000; // 穿墙道具持续10秒
    private static final int ENEMY_KILLER_DURATION = 10000; // 杀敌道具也改为10秒

    // 穿墙道具状态
    private boolean isWallPassActive = false;
    private long wallPassEndTime = 0; // 独立的结束时间
    private boolean isWallPassUsed = false; // 是否已使用过

    // 杀敌道具状态
    private boolean isEnemyKillerActive = false;
    private long enemyKillerEndTime = 0; // 独立的结束时间
    private boolean isEnemyKillerUsed = false; // 是否已使用过

    // 道具标签定义
    private JLabel powerUpLabel = new JLabel("穿墙道具: 未激活"); // 穿墙标签
    private JLabel powerUpLabel2 = new JLabel("杀敌道具: 未激活"); // 杀敌标签


    private List<PowerUp> powerUps = new ArrayList<>();
    private BranchGroup powerUpGroup; // 存放所有道具的组


    private long startTime; // 记录游戏开始时间
    private Timer timer; // 用于正计时的Timer对象
    private JLabel timerLabel = new JLabel("用时: 0s"); // 正计时标签

    // 生命值相关
    private int playerLives = 3; // 初始3点生命
    private JLabel livesLabel = new JLabel("生命值: 3"); // 生命值显示标签

    // 定义迷宫单元格状态
    private static final int WALL = 1;
    private static final int PATH = 0;
    private int[][] maze; // 添加这个成员变量


    private BranchGroup sceneRoot;

    private static final int MAZE_SIZE = 15;
    private static final float WALL_HEIGHT = 0.5f;
    private static final float CELL_SIZE = 1.0f;

    // 玩家相关参数
    private TransformGroup playerTransformGroup;
    private float playerX = 1.0f;  // 玩家起点X坐标
    private float playerZ = 1.0f;  // 玩家起点Z坐标
    private float playerSize = 0.3f;
    private float playerSpeed = 0.2f;

    // 敌人相关
    private List<Enemy> enemies = new ArrayList<>();
    private static final int ENEMY_COUNT = 1; // 敌人数量
    private BranchGroup enemyGroup; // 存放所有敌人的组

    // 相机控制参数
    private float cameraHeight = 10.0f;
    private float cameraX = 1.0f;  // 调整为玩家初始位置附近
    private float cameraZ = -3.0f; // 调整为玩家后方，便于观察
    private float cameraAngle = 0.0f;  // 初始角度看向玩家
    private float cameramoveSpeed = 0.2f;
    private float cameraturnSpeed = 0.05f;

    private SimpleUniverse universe;
    private TransformGroup cameraTransformGroup;
    private Canvas3D canvas;

    // 视角状态控制（true:第一人称，false:第三人称）
    private boolean isFirstPerson = false;


    // 游戏状态控制
    private boolean gameOver = false;
    private BranchGroup confettiGroup;  // 存放彩带粒子的组

    // 彩带粒子相关
    private static final int CONFETTI_COUNT = 200;  // 彩带数量
    private Confetti[] confettiParticles;  // 彩带领数组
    private float endRadius = 0.5f;  // 终点检测半径（判断玩家是否到达终点）

    // 起点和终点坐标
    private int startX = 1;
    private int startZ = 1;
    private int endX = 13;
    private int endZ = 13;

    public MazePlot3() {
        setLayout(new BorderLayout());
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
        canvas = new Canvas3D(config);
        add("Center", canvas);

        // 创建顶部面板，使用FlowLayout并右对齐
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        topPanel.setBackground(new Color(135, 206, 235)); // 设置半透明背景

        // 添加正计时标签
        timerLabel = new JLabel("用时: 0s");
        timerLabel.setFont(new Font("", Font.BOLD, 24));
        topPanel.add(timerLabel);


        // 添加生命值标签
        livesLabel.setForeground(Color.WHITE);
        livesLabel.setFont(new Font("", Font.BOLD, 24));
        topPanel.add(livesLabel);


        // 在顶部面板添加道具状态标签
        powerUpLabel.setForeground(Color.WHITE);
        powerUpLabel.setFont(new Font("", Font.BOLD, 24));
        powerUpLabel2.setForeground(Color.WHITE);
        powerUpLabel2.setFont(new Font("", Font.BOLD, 24));
        topPanel.add(powerUpLabel);
        topPanel.add(powerUpLabel2); // 新增：添加杀敌道具标签


        // 初始化设置按钮
        JButton settingsButton = new JButton();
        try {
            // 加载齿轮图标（根据实际路径调整）
            ImageIcon gearIcon = new ImageIcon(getClass().getResource("/img/齿轮.png"));
            // 缩放图标至合适大小（如20x20）
            Image scaledImage = gearIcon.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH);
            settingsButton.setIcon(new ImageIcon(scaledImage));
        } catch (Exception e) {
            // 若图标加载失败，显示文字"设置"
            settingsButton.setText("设置");
        }
        settingsButton.setPreferredSize(new Dimension(30, 30)); // 设置按钮大小
        settingsButton.setToolTipText("游戏设置"); // 鼠标悬停提示

        // 添加按钮点击事件：显示游戏介绍
        settingsButton.addActionListener(e -> {
            // 创建游戏介绍弹窗
            JFrame infoFrame = new JFrame("游戏介绍");
            infoFrame.setSize(800, 600);
            infoFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 关闭弹窗不影响主游戏
            infoFrame.setLocationRelativeTo(canvas); // 弹窗位置居中于主窗口

            // 创建文本区域显示游戏介绍
            JTextArea infoTextArea = new JTextArea();
            infoTextArea.setText("迷宫玩法介绍：\n" +
                    "(本迷宫使用键盘操纵,暂不用鼠标，一进入游戏会自动切换成中文输入法，请按shift切换成英文操作)\n" +
                    "玩家为蓝球，敌人为红球，道具为其他颜色立方体，请按照如下规则抵达终点（旗帜）\n" +
                    "1.视角与操控\n" +
                    "迷宫有第一和第三视角，初始视角是第三人视角\n" +
                    "Z切换成第三视角\n" +
                    "X切换成第一视角（第一视角下与墙壁过近会出现视角的穿模)\n" +
                    "相机的视角：\n" +
                    "W相机前进\n" +
                    "S相机后退\n" +
                    "A相机左转\n" +
                    "D相机右转\n" +
                    "Q相机上拉\n" +
                    "E相机下降\n" +
                    "玩家的移动：\n" +
                    "UP玩家前进\n" +
                    "DOWN玩家后退\n" +
                    "LEFT玩家左移\n" +
                    "RIGHT玩家右移\n" +
                    "在Z视角下，上述十个按键都可操作，此时相机未绑定玩家，不会跟随玩家移动而移动\n" +
                    "在X视角下，只可操作UP/DOWN/LEFT/RIGHT键，但此时相机视角绑定玩家，会跟随玩家移动\n" +
                    "2.生命\n" +
                    "玩家初始生命值为3，每触碰一次敌人生命值减1，触发伤害冷却约2s（玩家闪烁），冷却时间内敌人不得伤害，请尽快躲避，生命值清零游戏失败立即结束\n" +
                    "3.道具\n" +
                    "玩家可拾取两种道具，一种是穿墙道具（绿色），一种是杀敌道具（橙色），二者触碰之后，均触发10s使用倒计时\n" +
                    "拾取穿墙道具后玩家变成绿色，可以穿墙且此时是免疫于敌人的（不掉血），面板显示倒计时，10s后恢复原色蓝色，面板显示状态为已使用\n" +
                    "拾取杀敌道具后玩家变成黄色，可以杀死敌人，面板显示倒计时，10s后恢复原色蓝色，面板显示状态为已使用\n" +
                    "注意，两个道具不能同时使用，且均为一次性使用\n" +
                    "4.计时与闯关\n" +
                    "游戏会记录从开始到抵达终点的时间，抵达终点则闯关成功");
            infoTextArea.setLineWrap(true); // 自动换行
            infoTextArea.setWrapStyleWord(true); // 按单词换行
            infoTextArea.setEditable(false); // 禁止编辑
            infoTextArea.setFont(new Font("宋体", Font.PLAIN, 24)); // 设置字体

            // 添加滚动条（文本过长时）
            JScrollPane scrollPane = new JScrollPane(infoTextArea);
            infoFrame.add(scrollPane);

            // 显示弹窗
            infoFrame.setVisible(true);
        });

        // 将按钮添加到顶部面板
        topPanel.add(settingsButton);

        add(topPanel, BorderLayout.NORTH); // 将顶部面板添加到主布局的上方

        universe = new SimpleUniverse(canvas);
        BranchGroup scene = createSceneGraph();
        universe.addBranchGraph(scene);


        // 初始化彩带粒子
        confettiParticles = new Confetti[CONFETTI_COUNT];
        Random random = new Random();
        for (int i = 0; i < CONFETTI_COUNT; i++) {
            confettiParticles[i] = new Confetti(random);
        }

        // 设置键盘控制
        canvas.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                handleKeyPress(e);
            }
        });
        canvas.setFocusable(true);
        canvas.requestFocus();

        // 初始化正计时
        startTime = System.currentTimeMillis();
        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (!gameOver) {
                    long elapsedTime = System.currentTimeMillis() - startTime;
                    int seconds = (int) (elapsedTime / 1000);
                    updateTimerDisplay(seconds);
                }
            }
        }, 0, 1000); // 每秒更新一次

        // 道具倒计时定时更新（每秒一次）
        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (!gameOver) {
                    updatePowerUpStatus(); // 检查是否过期
                    updatePowerUpDisplay(); // 刷新显示
                }
            }
        }, 0, 1000); // 每秒执行一次

        // 启动敌人移动动画
        startEnemyMovement();

    }

    //2.三种内部类（道具，敌人，彩带）

    public enum Type {
        WALL_PASS,  // 穿墙
        ENEMY_KILLER // 杀敌
    }

    private  class PowerUp {

        private Type type; // 道具类型
        private  final Color3f WALL_PASS_COLOR = new Color3f(0.2f, 1.0f, 0.2f); // 绿色
        private  final Color3f ENEMY_KILLER_COLOR = new Color3f(0.8f, 0.3f, 0.0f); // 橙色（杀敌道具）
        private TransformGroup transformGroup;
        private float x, z;  // 位置（y固定）
        private boolean isActive = true;  // 道具是否有效
        private float duration = 10000;   // 道具效果持续时间（毫秒）

        public PowerUp(float startX, float startZ, Type type) {
            this.x = startX;
            this.z = startZ;
            this.type = type;


            // 初始化transformGroup并设置权限
            transformGroup = new TransformGroup();
            transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); // 允许修改变换

            // 根据类型设置持续时间（均为10秒）
            duration = (type == Type.WALL_PASS) ? WALL_PASS_DURATION : ENEMY_KILLER_DURATION;

            // 外观（根据类型设置颜色）
            Appearance app = new Appearance();
            Color3f color = (type == Type.WALL_PASS) ? WALL_PASS_COLOR : ENEMY_KILLER_COLOR;
            Material mat = new Material(color, color, color, color, 100.0f);
            mat.setLightingEnable(true);
            app.setMaterial(mat);

            // 道具模型（小立方体）
            Box powerUpBox = new Box(0.2f, 0.2f, 0.2f, Primitive.GENERATE_NORMALS, app);
            transformGroup.addChild(powerUpBox);
            updatePosition();//设置初始位置
        }

        // 更新道具位置
        private void updatePosition() {
            Transform3D transform = new Transform3D();
            transform.setTranslation(new Vector3f(x, 0.2f, z)); // y坐标稍高于地面
            transformGroup.setTransform(transform);
        }

        // 获取道具位置
        public float getX() { return x; }
        public float getZ() { return z; }

        // 获取道具变换组
        public TransformGroup getTransformGroup() {
            return transformGroup;
        }

        // 激活道具
        public void activate() {
            isActive = false;
            // 隐藏道具
            Transform3D transform = new Transform3D();
            transform.setTranslation(new Vector3f(x, -1.0f, z)); // 移到地下隐藏
            transformGroup.setTransform(transform);
        }

        // 检查道具是否有效
        public boolean isActive() {
            return isActive;
        }

        // 获取道具效果持续时间
        public float getDuration() {
            return duration;
        }

        // 获取道具类型
        public Type getType() {
            return type;
        }

    }


    // 爆破效果内部类
    private class Explosion {
        private BranchGroup branchGroup;
        private BranchGroup explosionContainer; // 保存容器节点
        private List<TransformGroup> fragments; // 爆破碎片
        private int fragmentCount = 12; // 碎片数量
        private float[] fragmentSpeeds; // 碎片速度
        private float[] fragmentAngles; // 碎片角度
        private boolean isActive = true;

        public Explosion(float x, float z) {
            branchGroup = new BranchGroup();
            branchGroup.setCapability(BranchGroup.ALLOW_DETACH);
            fragments = new ArrayList<>();
            fragmentSpeeds = new float[fragmentCount];
            fragmentAngles = new float[fragmentCount];
            Random random = new Random();

            // 创建爆破碎片（彩色小方块）
            for (int i = 0; i < fragmentCount; i++) {
                // 随机颜色
                Color3f color = new Color3f(
                        random.nextFloat() * 0.8f + 0.2f,
                        random.nextFloat() * 0.3f,
                        0.0f // 偏红色系
                );

                // 创建碎片
                Appearance app = new Appearance();
                Material mat = new Material(color, color, color, color, 50.0f);
                mat.setLightingEnable(true);
                app.setMaterial(mat);

                Box fragment = new Box(0.08f, 0.08f, 0.08f, Primitive.GENERATE_NORMALS, app);
                TransformGroup tg = new TransformGroup();
                tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
                tg.addChild(fragment);
                branchGroup.addChild(tg);
                fragments.add(tg);

                // 随机速度和角度
                fragmentSpeeds[i] = 0.02f + random.nextFloat() * 0.03f;
                fragmentAngles[i] = random.nextFloat() * (float)(2 * Math.PI);
            }

            // 初始位置（爆炸中心点）
            Transform3D transform = new Transform3D();
            transform.setTranslation(new Vector3f(x, 0.25f, z));
            TransformGroup centerTg = new TransformGroup(transform);
            centerTg.addChild(branchGroup);

            // 用BranchGroup包装后再添加
            BranchGroup explosionContainer = new BranchGroup();
            explosionContainer.setCapability(BranchGroup.ALLOW_DETACH);
            explosionContainer.addChild(centerTg);
            sceneRoot.addChild(explosionContainer);

            // 保存容器引用
            this.explosionContainer = explosionContainer;

            // 启动爆炸动画
            startAnimation();
        }

        // 爆炸动画逻辑
        private void startAnimation() {
            new Thread(() -> {
                int lifetime = 0;
                while (isActive && lifetime < 60) { // 持续约3秒（60*50ms）
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    // 更新碎片位置
                    for (int i = 0; i < fragmentCount; i++) {
                        Transform3D t = new Transform3D();
                        fragments.get(i).getTransform(t);
                        Vector3f pos = new Vector3f();
                        t.get(pos);

                        // 沿角度移动
                        pos.x += (float)Math.sin(fragmentAngles[i]) * fragmentSpeeds[i];
                        pos.z += (float)Math.cos(fragmentAngles[i]) * fragmentSpeeds[i];
                        pos.y += 0.01f; // 略微上升

                        // 速度衰减
                        fragmentSpeeds[i] *= 0.95f;

                        t.setTranslation(pos);
                        fragments.get(i).setTransform(t);
                    }
                    lifetime++;
                }

                // 动画结束后移除爆炸效果
                sceneRoot.removeChild(explosionContainer); // 移除正确的BranchGroup节点

            }).start();
        }
    }

    // 敌人内部类
    private class Enemy {
        private TransformGroup transformGroup;
        private float x, z;  // 位置（y固定）
        private float angle; // 移动方向
        private float baseSpeed = 0.03f; // 基础速度
        private float speed; // 实际移动速度
        private int moveCounter; // 移动计数，用于改变方向
        private int changeDirectionInterval; // 改变方向的间隔步数

        public Enemy(float startX, float startZ) {
            x = startX;
            z = startZ;
            angle = new Random().nextFloat() * (float)(2 * Math.PI); // 随机初始方向
            speed = baseSpeed; // 初始速度
            moveCounter = 0;
            changeDirectionInterval = new Random().nextInt(50) + 50; // 50-100步改变一次方向

            // 创建敌人变换组
            transformGroup = new TransformGroup();
            transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

            // 创建敌人外观（红色）
            Appearance app = new Appearance();
            Color3f color = new Color3f(1.0f, 0.2f, 0.2f); // 红色敌人
            Material mat = new Material(color, color, color, color, 80.0f);
            mat.setLightingEnable(true);
            app.setMaterial(mat);

            // 敌人模型（稍大的球体）
            Sphere enemySphere = new Sphere(0.25f, Primitive.GENERATE_NORMALS, app);
            transformGroup.addChild(enemySphere);

            // 设置初始位置
            updatePosition();
        }

        public void kill() {
            isAlive = false;
            // 将敌人模型移到地下（y坐标设为-1.0f），使其隐藏
            Transform3D hideTransform = new Transform3D();
            hideTransform.setTranslation(new Vector3f(x, -1.0f, z)); // y=-1.0f在地面以下
            transformGroup.setTransform(hideTransform);
        }

        // 判断是否存活
        public boolean isAlive() {
            return isAlive;
        }

        // 敌人update方法中添加：检测并避开道具
        private void avoidPowerUps() {
            for (PowerUp powerUp : powerUps) {
                if (powerUp.isActive()) {
                    float distanceToPowerUp = (float)Math.sqrt(
                            Math.pow(x - powerUp.getX(), 2) + Math.pow(z - powerUp.getZ(), 2)
                    );
                    if (distanceToPowerUp < 2.0f) { // 距离道具过近
                        // 转向远离道具的方向
                        float dx = x - powerUp.getX();
                        float dz = z - powerUp.getZ();
                        angle = (float)Math.atan2(dx, dz); // 朝向远离道具的方向
                        break;
                    }
                }
            }
        }

        // 重写update方法，仅保留随机移动和避道具
        public void update() {
            if (!isAlive) return; // 死亡状态不移动

            avoidPowerUps(); // 保留避道具逻辑
            randomMove(); // 直接使用随机移动
        }

        private void randomMove() {
            moveCounter++;
            // 定期改变方向
            if (moveCounter >= changeDirectionInterval) {
                angle = new Random().nextFloat() * (float)(2 * Math.PI);
                moveCounter = 0;
                changeDirectionInterval = new Random().nextInt(50) + 50;
            }

            // 计算新位置
            float newX = x + (float)Math.sin(angle) * speed;
            float newZ = z + (float)Math.cos(angle) * speed;

            // 强化碰撞检测：如果新位置无效，直接改变方向
            if (!isPositionValid(newX, newZ)) {
                angle = new Random().nextFloat() * (float)(2 * Math.PI); // 立即转向
                return; // 不移动，直接返回
            }

            // 有效位置则移动
            x = newX;
            z = newZ;
            updatePosition();
        }

        private boolean isPositionValid(float x, float z) {
            int cellX = Math.round(x);
            int cellZ = Math.round(z);

            // 强化边界检查：不允许靠近边缘
            if (cellX <= 0 || cellX >= MAZE_SIZE - 1 ||
                    cellZ <= 0 || cellZ >= MAZE_SIZE - 1) {
                return false;
            }

            // 检查是否是墙
            return maze[cellZ][cellX] == PATH;
        }

        // 更新变换组位置
        private void updatePosition() {
            Transform3D transform = new Transform3D();
            transform.setTranslation(new Vector3f(x, 0.25f, z)); // y坐标设为球体半径
            transformGroup.setTransform(transform);
        }

        // 获取敌人当前位置
        public float getX() { return x; }
        public float getZ() { return z; }

        // 获取敌人变换组
        public TransformGroup getTransformGroup() {
            return transformGroup;
        }
    }


    //彩带粒子内部类
    private class Confetti {
        private TransformGroup transformGroup;
        private BranchGroup branchGroup;  // 改为BranchGroup
        private float x, y, z;  // 位置
        private float dx, dy, dz;  // 移动速度
        private float rotation;  // 旋转角度
        private float rotationSpeed;  // 旋转速度
        private Color3f color;  // 颜色

        public Confetti(Random random) {
            // 初始化彩带位置（终点周围）
            x = endX + (random.nextFloat() - 0.5f) * 3;
            z = endZ + (random.nextFloat() - 0.5f) * 3;
            y = 5 + random.nextFloat() * 5;  // 从高处落下

            // 随机速度和旋转
            dx = (random.nextFloat() - 0.5f) * 0.1f;
            dy = -0.05f - random.nextFloat() * 0.05f;  // 向下运动
            dz = (random.nextFloat() - 0.5f) * 0.1f;
            rotationSpeed = (random.nextFloat() - 0.5f) * 0.1f;

            // 随机颜色
            color = new Color3f(
                    random.nextFloat(),
                    random.nextFloat(),
                    random.nextFloat()
            );

            // 创建BranchGroup作为根节点
            branchGroup = new BranchGroup();
            branchGroup.setCapability(BranchGroup.ALLOW_DETACH);  // 允许从场景中移除

            // 创建彩带形状（小方块）
            transformGroup = new TransformGroup();
            transformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

            Appearance app = new Appearance();
            Material mat = new Material(color, color, color, color, 80.0f);
            mat.setLightingEnable(true);
            app.setMaterial(mat);

            Box confettiBox = new Box(0.05f, 0.05f, 0.05f, Primitive.GENERATE_NORMALS, app);

            transformGroup.addChild(confettiBox);
            branchGroup.addChild(transformGroup);  //将TransformGroup添加到BranchGroup

        }

        // 更新彩带位置和旋转
        public void update() {
            x += dx;
            y += dy;
            z += dz;
            rotation += rotationSpeed;

            // 超出范围后重置位置（循环飘落效果）
            if (y < 0) {
                y = 10;
            }

            // 应用变换
            Transform3D t = new Transform3D();
            Transform3D rot = new Transform3D();
            rot.rotY(rotation);  // 绕Y轴旋转
            t.setTranslation(new Vector3f(x, y, z));
            t.mul(rot);
            transformGroup.setTransform(t);
        }
    }


    //3.各种内部类的以及其他的相关方法

    // 创建道具
    private void createPowerUps() {
        powerUpGroup = new BranchGroup();
        powerUpGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        powerUpGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

        Random random = new Random();

        // 1. 生成绿色穿墙道具（远离敌人）
        float wallPassX = 0, wallPassZ = 0;
        boolean wallPassValid = false;

        // 尝试100次生成远离敌人的位置（至少6个单位）
        for (int attempt = 0; attempt < 100; attempt++) {
            // 在迷宫中间区域生成
            wallPassX = 2 + random.nextInt(MAZE_SIZE - 4);
            wallPassZ = 2 + random.nextInt(MAZE_SIZE - 4);

            // 检查是否为有效路径
            if (!isPositionValid(wallPassX, wallPassZ)) {
                continue;
            }

            // 检查是否远离所有敌人（至少6个单位）
            boolean farFromAllEnemies = true;
            for (Enemy enemy : enemies) {
                float distance = (float)Math.sqrt(
                        Math.pow(wallPassX - enemy.getX(), 2) +
                                Math.pow(wallPassZ - enemy.getZ(), 2)
                );
                if (distance < 6.0f) {
                    farFromAllEnemies = false;
                    break;
                }
            }

            // 同时远离起点，避免太容易获取
            float distanceFromStart = (float)Math.sqrt(
                    Math.pow(wallPassX - startX, 2) +
                            Math.pow(wallPassZ - startZ, 2)
            );

            if (farFromAllEnemies && distanceFromStart > 3.0f) {
                wallPassValid = true;
                break;
            }
        }

        // 如果多次尝试失败，使用降级方案（至少4个单位）
        if (!wallPassValid) {
            for (int attempt = 0; attempt < 100; attempt++) {
                wallPassX = 1 + random.nextInt(MAZE_SIZE - 2);
                wallPassZ = 1 + random.nextInt(MAZE_SIZE - 2);

                if (isPositionValid(wallPassX, wallPassZ)) {
                    boolean farEnough = true;
                    for (Enemy enemy : enemies) {
                        float distance = (float)Math.sqrt(
                                Math.pow(wallPassX - enemy.getX(), 2) +
                                        Math.pow(wallPassZ - enemy.getZ(), 2)
                        );
                        if (distance < 4.0f) {
                            farEnough = false;
                            break;
                        }
                    }
                    if (farEnough) {
                        wallPassValid = true;
                        break;
                    }
                }
            }
        }

        // 如果仍然失败，使用最基本的有效位置（确保能生成）
        if (!wallPassValid) {
            wallPassX = 1 + random.nextInt(MAZE_SIZE - 2);
            wallPassZ = 1 + random.nextInt(MAZE_SIZE - 2);
            while (!isPositionValid(wallPassX, wallPassZ)) {
                wallPassX = 1 + random.nextInt(MAZE_SIZE - 2);
                wallPassZ = 1 + random.nextInt(MAZE_SIZE - 2);
            }
        }

        // 创建绿色穿墙道具
        PowerUp wallPassPowerUp = new PowerUp(wallPassX, wallPassZ, Type.WALL_PASS);
        powerUps.add(wallPassPowerUp);
        powerUpGroup.addChild(wallPassPowerUp.getTransformGroup());

        // 2. 生成黄色杀敌道具（靠近敌人）
        float enemyKillerX = 0, enemyKillerZ = 0;
        boolean enemyKillerValid = false;

        // 尝试100次生成靠近敌人的位置（1.5-3个单位之间）
        for (int attempt = 0; attempt < 100; attempt++) {
            // 以第一个敌人为参考点
            Enemy referenceEnemy = enemies.get(0);
            float baseX = referenceEnemy.getX();
            float baseZ = referenceEnemy.getZ();

            // 在敌人周围随机偏移
            enemyKillerX = baseX + (random.nextFloat() - 0.5f) * 4; // -2到+2之间的偏移
            enemyKillerZ = baseZ + (random.nextFloat() - 0.5f) * 4;

            // 检查是否为有效路径
            if (!isPositionValid(enemyKillerX, enemyKillerZ)) {
                continue;
            }

            // 检查是否靠近敌人（1.5-3个单位）
            float distance = (float)Math.sqrt(
                    Math.pow(enemyKillerX - baseX, 2) +
                            Math.pow(enemyKillerZ - baseZ, 2)
            );

            if (distance >= 1.5f && distance <= 3.0f) {
                enemyKillerValid = true;
                break;
            }
        }

        // 如果多次尝试失败，放宽条件（1-4个单位）
        if (!enemyKillerValid && !enemies.isEmpty()) {
            Enemy referenceEnemy = enemies.get(0);
            for (int attempt = 0; attempt < 100; attempt++) {
                enemyKillerX = referenceEnemy.getX() + (random.nextFloat() - 0.5f) * 6;
                enemyKillerZ = referenceEnemy.getZ() + (random.nextFloat() - 0.5f) * 6;

                if (isPositionValid(enemyKillerX, enemyKillerZ)) {
                    float distance = (float)Math.sqrt(
                            Math.pow(enemyKillerX - referenceEnemy.getX(), 2) +
                                    Math.pow(enemyKillerZ - referenceEnemy.getZ(), 2)
                    );

                    if (distance >= 1.0f && distance <= 4.0f) {
                        enemyKillerValid = true;
                        break;
                    }
                }
            }
        }

        // 如果仍然失败，使用普通有效位置
        if (!enemyKillerValid) {
            enemyKillerX = 1 + random.nextInt(MAZE_SIZE - 2);
            enemyKillerZ = 1 + random.nextInt(MAZE_SIZE - 2);
            while (!isPositionValid(enemyKillerX, enemyKillerZ)) {
                enemyKillerX = 1 + random.nextInt(MAZE_SIZE - 2);
                enemyKillerZ = 1 + random.nextInt(MAZE_SIZE - 2);
            }
        }

        // 创建黄色杀敌道具
        PowerUp enemyKillerPowerUp = new PowerUp(enemyKillerX, enemyKillerZ, Type.ENEMY_KILLER);
        powerUps.add(enemyKillerPowerUp);
        powerUpGroup.addChild(enemyKillerPowerUp.getTransformGroup());
    }

    // 检查位置是否有效（不与墙碰撞）
    private boolean isPositionValid(float x, float z) {
        int cellX = Math.round(x);
        int cellZ = Math.round(z);

        // 检查是否超出边界
        if (cellX < 0 || cellX >= MAZE_SIZE || cellZ < 0 || cellZ >= MAZE_SIZE) {
            return false;
        }

        // 检查是否是墙
        return maze[cellZ][cellX] == PATH;
    }

    private void updateTimerDisplay(int seconds) {
        SwingUtilities.invokeLater(() -> {
            timerLabel.setText("用时: " + seconds + "s");
            timerLabel.setFont(new Font("", Font.BOLD, 24));
        });
    }

    // 更新生命值显示
    private void updateLivesDisplay() {
        SwingUtilities.invokeLater(() -> {
            livesLabel.setText("生命值: " + playerLives);
        });
    }

    private void showSuccessMessage() {
        //创建组件容器
        JFrame successFrame = new JFrame("闯关成功");
        successFrame.setSize(500, 300);
        successFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 创建标签
        String message = "恭喜闯关成功！";
        JLabel successLabel = new JLabel(message);
        successLabel.setFont(new Font("", Font.BOLD, 32));
        //successLabel.setForeground(Color.WHITE);//前景色
        //successLabel.setBackground(new Color(108,92,231));
        successLabel.setHorizontalAlignment(SwingConstants.CENTER);//居中对齐
        // 创建按钮
        JPanel buttonPanel = new JPanel();
        JButton button = new JButton("确定");
        button.setBackground(new Color(92, 189, 231));
        //button.setForeground(Color.WHITE);
        button.setFont(new Font("", Font.BOLD, 32));
        //button.setBorder(null);
        button.setFocusPainted(false);
        buttonPanel.add(button);
        // 添加按钮点击事件
        button.addActionListener(e -> {
            // 关闭弹窗和迷宫Maze窗口
            Window window = SwingUtilities.getWindowAncestor(MazePlot3.this);
            if (window != null) {
                window.dispose(); // 关闭当前窗口
            }
            successFrame.dispose();
            com.mazegame.frontend.MainFrame.cardLayout.show(com.mazegame.frontend.MainFrame.cardPanel, "BUFFERPANEL");
        });
        // 添加组件
        successFrame.add(successLabel);
        successFrame.add(buttonPanel, BorderLayout.SOUTH);
        successFrame.setVisible(true);
    }
    private void showFailureMessage() {
        //创建组件容器
        JFrame failureFrame = new JFrame("游戏结束");
        failureFrame.setSize(500, 300);
        failureFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 创建标签
        String message = "很遗憾，游戏结束！";
        JLabel failureLabel = new JLabel(message);
        failureLabel.setFont(new Font("", Font.BOLD, 32));
        //failureLabel.setBackground(new Color(108,92,231));
        failureLabel.setHorizontalAlignment(SwingConstants.CENTER);//居中对齐
        // 创建按钮
        JPanel buttonPanel = new JPanel();
        JButton button = new JButton("确定");
        button.setBackground(new Color(92, 189, 231));
        button.setFont(new Font("", Font.BOLD, 32));
        //button.setBorder(null);
        button.setFocusPainted(false);
        buttonPanel.add(button);
        // 添加按钮点击事件
        button.addActionListener(e -> {
            // 关闭弹窗和迷宫Maze窗口
            Window window = SwingUtilities.getWindowAncestor(MazePlot3.this);
            if (window != null) {
                window.dispose(); // 关闭当前窗口
            }
            failureFrame.dispose();
            com.mazegame.frontend.MainFrame.cardLayout.show(com.mazegame.frontend.MainFrame.cardPanel, "MAINPANEL");
        });
        // 添加组件
        failureFrame.add(failureLabel);
        failureFrame.add(buttonPanel, BorderLayout.SOUTH);
        failureFrame.setVisible(true);

    }

    private int[][] generateMaze() {
        int[][] newMaze = new int[MAZE_SIZE][MAZE_SIZE];
        // 初始化所有单元格为墙壁
        for (int z = 0; z < MAZE_SIZE; z++) {
            for (int x = 0; x < MAZE_SIZE; x++) {
                newMaze[z][x] = WALL;
            }
        }

        // 从起点开始进行深度优先搜索
        boolean[][] visited = new boolean[MAZE_SIZE][MAZE_SIZE];
        dfsMazeGeneration(newMaze, visited, startZ, startX);

        return newMaze;
    }

    private void dfsMazeGeneration(int[][] maze, boolean[][] visited, int z, int x) {
        visited[z][x] = true;
        maze[z][x] = PATH;

        // 随机打乱方向顺序，以增加随机性
        int[] directions = {0, 1, 2, 3};
        shuffleArray(directions);

        for (int dir : directions) {
            int newZ = z;
            int newX = x;
            switch (dir) {
                case 0: // 北
                    newZ -= 2;
                    break;
                case 1: // 东
                    newX += 2;
                    break;
                case 2: // 南
                    newZ += 2;
                    break;
                case 3: // 西
                    newX -= 2;
                    break;
            }

            if (newZ >= 0 && newZ < MAZE_SIZE && newX >= 0 && newX < MAZE_SIZE &&
                    !visited[newZ][newX]) {
                // 打通当前单元格和新单元格之间的墙壁
                if (dir == 0) {
                    maze[z - 1][x] = PATH;
                } else if (dir == 1) {
                    maze[z][x + 1] = PATH;
                } else if (dir == 2) {
                    maze[z + 1][x] = PATH;
                } else if (dir == 3) {
                    maze[z][x - 1] = PATH;
                }
                dfsMazeGeneration(maze, visited, newZ, newX);
            }
        }
    }

    private void shuffleArray(int[] array) {
        Random random = new Random();
        for (int i = array.length - 1; i > 0; i--) {
            int j = random.nextInt(i + 1);
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }


    private BranchGroup createSceneGraph() {
        BranchGroup objRoot = new BranchGroup();

        // 随机生成迷宫，并赋值给成员变量
        maze = generateMaze();

        // 创建迷宫
        objRoot.addChild(createMaze(maze));
        // 创建终点标记
        objRoot.addChild(createEndMarker());
        // 创建玩家
        createPlayer();
        objRoot.addChild(playerTransformGroup);
        // 创建敌人
        createEnemies();
        objRoot.addChild(enemyGroup);

        // 在初始化敌人之后添加
        // 创建道具
        createPowerUps();
        objRoot.addChild(powerUpGroup);

        // 设置光源
        objRoot.addChild(createLights());
        // 设置背景
        Background background = new Background(new Color3f(135/255.0f, 206/255.0f, 235/255.0f));
        background.setApplicationBounds(new BoundingSphere(new Point3d(0, 0, 0), 100.0));
        objRoot.addChild(background);
        // 设置雾效
        Fog fog = new LinearFog(new Color3f(0.7f, 0.8f, 0.9f), 10.0f, 20.0f);
        fog.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100.0));
        objRoot.addChild(fog);
        // 设置相机
        setupCamera(objRoot);
        // 允许场景图动态更新
        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

        // 创建彩带组（用于存放所有彩带粒子）
        confettiGroup = new BranchGroup();
        confettiGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        confettiGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

        // 创建中间TransformGroup容器
        TransformGroup confettiContainer = new TransformGroup();
        confettiContainer.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        confettiContainer.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        confettiContainer.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        confettiGroup.addChild(confettiContainer);

        objRoot.addChild(confettiGroup);

        // 添加"闯关成功"文字
        objRoot.addChild(createSuccessMessage());

        sceneRoot = objRoot;
        return objRoot;

    }



    // 创建敌人
    private void createEnemies() {
        enemyGroup = new BranchGroup();
        enemyGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        enemyGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

        enemies.clear();
        Random random = new Random();
        final float MIN_DISTANCE_FROM_END = 5.0f; // 与终点的最小距离

        // 创建指定数量的敌人
        for (int i = 0; i < ENEMY_COUNT; i++) {
            float enemyX, enemyZ;
            int attempts = 0;
            do {
                enemyX = random.nextInt(MAZE_SIZE - 2) + 1; // 避免放在边缘
                enemyZ = random.nextInt(MAZE_SIZE - 2) + 1;
                attempts++;

                // 如果尝试超过50次仍无法找到合适位置，放宽终点距离限制
                if (attempts > 50) {
                    break;
                }

                // 计算与终点的距离
                float distanceToEnd = (float)Math.sqrt(
                        Math.pow(enemyX - endX, 2) + Math.pow(enemyZ - endZ, 2)
                );

            } while (maze[(int)enemyZ][(int)enemyX] != PATH ||
                    (Math.abs(enemyX - startX) < 3 && Math.abs(enemyZ - startZ) < 3) || // 远离起点
                    (Math.abs(enemyX - endX) < MIN_DISTANCE_FROM_END && Math.abs(enemyZ - endZ) < MIN_DISTANCE_FROM_END)); // 远离终点

            Enemy enemy = new Enemy(enemyX, enemyZ);
            enemies.add(enemy);
            enemyGroup.addChild(enemy.getTransformGroup());
        }
    }


    // 启动敌人移动动画，具有提速逻辑（如每30秒提速一次）
    private void startEnemyMovement() {
        new Thread(() -> {
            long lastSpeedUpTime = System.currentTimeMillis();
            while (!gameOver) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 每30秒敌人提速5%
                long currentTime = System.currentTimeMillis();
                if (currentTime - lastSpeedUpTime > 30000) {
                    for (Enemy enemy : enemies) {
                        enemy.speed *= 1.05f; // 最大不超过0.08f
                        if (enemy.speed > 0.08f) enemy.speed = 0.08f;
                    }
                    lastSpeedUpTime = currentTime;
                }

                // 更新敌人位置
                for (Enemy enemy : enemies) {
                    enemy.update();
                }
                checkEnemyCollision();
            }
        }).start();
    }

    // 检测玩家与敌人的碰撞
    private void checkEnemyCollision() {

        // 穿墙状态下不会被敌人伤害
        if (gameOver || isWallPassActive) return;

        // 检查是否在无敌状态
        if (isInvincible) {
            if (System.currentTimeMillis() > invincibilityEndTime) {
                isInvincible = false;
                // 恢复玩家颜色
                changePlayerColor(new Color3f(0.2f, 0.2f, 1.0f));
            }
            return;
        }


        // 杀敌状态：玩家碰撞敌人 -> 敌人死亡+爆破
        if (isEnemyKillerActive) {
            for (Enemy enemy : enemies) {
                if (enemy.isAlive()) { // 只处理存活敌人
                    float distance = (float)Math.sqrt(
                            Math.pow(playerX - enemy.getX(), 2) +
                                    Math.pow(playerZ - enemy.getZ(), 2)
                    );

                    if (distance < (playerSize + 0.25f)) {
                        enemy.kill(); // 敌人死亡
                        new Explosion(enemy.getX(), enemy.getZ()); // 触发爆破效果
                        break;
                    }
                }
            }
            return;
        }


        // 普通状态：敌人碰撞玩家 -> 减血
        // 检查是否在冷却时间内
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastHitTime < HIT_COOLDOWN) {
            return; // 冷却时间内不检测碰撞
        }

        for (Enemy enemy : enemies) {
            // 计算玩家与敌人之间的距离
            float distance = (float)Math.sqrt(
                    Math.pow(playerX - enemy.getX(), 2) +
                            Math.pow(playerZ - enemy.getZ(), 2)
            );

            // 如果距离小于玩家和敌人半径之和，发生碰撞
            if (distance < (playerSize + 0.25f)) {
                loseLife();
                // 简单的碰撞后击退效果
                playerX += (playerX - enemy.getX()) * 0.3f;
                playerZ += (playerZ - enemy.getZ()) * 0.3f;
                updatePlayerPosition();
                updateCameraPosition();

                // 启动无敌状态
                isInvincible = true;
                invincibilityEndTime = currentTime + HIT_COOLDOWN;
                flashCounter = 0;
                startInvincibilityFlash();

                break; // 一次只处理一次碰撞
            }
        }
    }


    private void startInvincibilityFlash() {
        new Thread(() -> {
            while (isInvincible && flashCounter < FLASH_COUNT) {
                try {
                    Thread.sleep(FLASH_INTERVAL);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                flashCounter++;
                if (flashCounter % 2 == 0) {
                    // 闪烁：显示玩家
                    changePlayerColor(new Color3f(0.2f, 0.2f, 1.0f));
                } else {
                    // 闪烁：隐藏玩家
                    changePlayerColor(new Color3f(0.0f, 0.0f, 0.0f));
                }
            }

            // 闪烁结束，恢复玩家颜色
            if (!gameOver) {
                changePlayerColor(new Color3f(0.2f, 0.2f, 1.0f));
            }
        }).start();
    }



    // 减少生命值
    private void loseLife() {

        if (isInvincible) {
            return; // 无敌状态下不减少生命值
        }
        playerLives--;
        updateLivesDisplay();

        // 如果生命值为0，游戏结束
        if (playerLives <= 0) {
            gameOver = true;
            showFailureMessage();
            timer.cancel();
        }
    }


    private TransformGroup createMaze(int[][] mazeArray) {
        TransformGroup mazeGroup = new TransformGroup();

        // 创建地板
        Appearance floorApp = new Appearance();
        Color3f floorColor = new Color3f(0.5f, 0.5f, 0.5f);
        Material floorMaterial = new Material(floorColor, floorColor, floorColor, floorColor, 80.0f);
        floorMaterial.setLightingEnable(true);
        floorApp.setMaterial(floorMaterial);

        Box floor = new Box(MAZE_SIZE/2.0f, 0.01f, MAZE_SIZE/2.0f, Primitive.GENERATE_NORMALS, floorApp);
        Transform3D floorTransform = new Transform3D();
        floorTransform.setTranslation(new Vector3f((MAZE_SIZE-1)/2.0f, -0.01f, (MAZE_SIZE-1)/2.0f));
        TransformGroup floorGroup = new TransformGroup(floorTransform);
        floorGroup.addChild(floor);
        mazeGroup.addChild(floorGroup);

        // 创建墙壁
        // 加载纹理图片
        //TextureLoader textureLoader = new TextureLoader("C:/Users/32408/Desktop/MyMaze/Test/src/main/resources/img/迷宫纹理.png", this);
        //TextureLoader textureLoader = new TextureLoader("C:/Users/32408/Desktop/MyMaze/Test/src/main/resources/img/灰石砖.png", this);
        TextureLoader textureLoader = new TextureLoader("C:\\AAAWJX\\暑期实训\\Test\\src\\main\\resources\\img\\墙2.png", this);
        Texture texture = textureLoader.getTexture();

        Appearance wallApp = new Appearance();
        // 设置纹理属性
        TextureAttributes texAttr = new TextureAttributes();
        texAttr.setTextureMode(TextureAttributes.MODULATE);
        wallApp.setTextureAttributes(texAttr);
        wallApp.setTexture(texture);

        // 其他材质设置（保持不变）
        Color3f wallColor = new Color3f(0.65f, 0.55f, 0.35f);
        Material wallMaterial = new Material(wallColor, wallColor, wallColor, wallColor, 80.0f);
        wallMaterial.setLightingEnable(true);
        wallApp.setMaterial(wallMaterial);

        for (int z = 0; z < MAZE_SIZE; z++) {
            for (int x = 0; x < MAZE_SIZE; x++) {
                if (mazeArray[z][x] == WALL) {
                    Box wall = new Box(CELL_SIZE/2.0f, WALL_HEIGHT/2.0f, CELL_SIZE/2.0f,
                            Primitive.GENERATE_NORMALS | Primitive.GENERATE_TEXTURE_COORDS, wallApp);
                    Transform3D wallTransform = new Transform3D();
                    wallTransform.setTranslation(new Vector3f(x, WALL_HEIGHT/2.0f, z));
                    TransformGroup wallGroup = new TransformGroup(wallTransform);
                    wallGroup.addChild(wall);
                    mazeGroup.addChild(wallGroup);
                }
            }
        }

        return mazeGroup;
    }

    private TransformGroup createEndMarker() {
        TransformGroup endMarkerGroup = new TransformGroup();

        // 创建旗杆（灰色圆柱体）
        Appearance poleApp = new Appearance();
        Color3f poleColor = new Color3f(0.6f, 0.6f, 0.6f);
        Material poleMaterial = new Material(poleColor, poleColor, poleColor, poleColor, 60.0f);
        poleMaterial.setLightingEnable(true);
        poleApp.setMaterial(poleMaterial);

        Cylinder pole = new Cylinder(0.05f, 1.2f, Primitive.GENERATE_NORMALS, poleApp);
        Transform3D poleTransform = new Transform3D();
        poleTransform.setTranslation(new Vector3f(endX, 0.6f, endZ));
        TransformGroup poleGroup = new TransformGroup(poleTransform);
        poleGroup.addChild(pole);

        // 创建旗面（红色矩形）
        Appearance flagApp = new Appearance();
        Color3f flagColor = new Color3f(1.0f, 0.2f, 0.2f);
        Material flagMaterial = new Material(flagColor, flagColor, flagColor, flagColor, 80.0f);
        flagMaterial.setLightingEnable(true);
        flagApp.setMaterial(flagMaterial);

        // 创建旗面几何信息
        float[] vertices = {
                0.0f, 1.2f, 0.0f,       // 旗杆顶部
                0.6f, 1.2f, 0.0f,       // 旗角1
                0.6f, 0.9f, 0.0f,       // 旗角2
                0.0f, 1.0f, 0.0f        // 旗杆中部
        };

        int[] indices = {0, 1, 2, 0, 2, 3};

        TriangleArray flagGeometry = new TriangleArray(vertices.length,
                TriangleArray.COORDINATES | TriangleArray.NORMALS);
        flagGeometry.setCoordinates(0, vertices);

        // 为旗面设置法向量
        Vector3f normal = new Vector3f(0.0f, 0.0f, 1.0f);
        Vector3f[] normals = new Vector3f[vertices.length / 3];
        Arrays.fill(normals, normal);
        flagGeometry.setNormals(0, normals);

        Shape3D flagShape = new Shape3D(flagGeometry, flagApp);
        Transform3D flagTransform = new Transform3D();
        flagTransform.setTranslation(new Vector3f(endX, 0.0f, endZ));
        TransformGroup flagGroup = new TransformGroup(flagTransform);
        flagGroup.addChild(flagShape);

        // 添加旗杆和旗面到终点标记组
        endMarkerGroup.addChild(poleGroup);
        endMarkerGroup.addChild(flagGroup);

        return endMarkerGroup;
    }

    private void createPlayer() {
        playerTransformGroup = new TransformGroup();
        playerTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

        // 玩家模型创建
        Appearance playerApp = new Appearance();

        // 添加修改材质的权限
        playerApp.setCapability(Appearance.ALLOW_MATERIAL_WRITE);

        Color3f playerColor = new Color3f(0.2f, 0.2f, 1.0f);
        Material playerMaterial = new Material(playerColor, playerColor, playerColor, playerColor, 80.0f);
        playerMaterial.setLightingEnable(true);
        playerApp.setMaterial(playerMaterial);

        Sphere playerSphere = new Sphere(playerSize, Primitive.GENERATE_NORMALS, playerApp);
        playerTransformGroup.addChild(playerSphere);

        // 初始位置
        updatePlayerPosition();
    }

    private void updatePlayerPosition() {
        Transform3D transform = new Transform3D();
        transform.setTranslation(new Vector3f(playerX, playerSize, playerZ));
        playerTransformGroup.setTransform(transform);
    }

    private Group createLights() {
        BranchGroup lights = new BranchGroup();

        // 环境光
        AmbientLight ambientLight = new AmbientLight(new Color3f(0.4f, 0.4f, 0.4f));
        ambientLight.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100.0));
        lights.addChild(ambientLight);

        // 方向光
        DirectionalLight directionalLight = new DirectionalLight(
                new Color3f(0.8f, 0.8f, 0.8f),
                new Vector3f(-1.0f, -1.0f, -1.0f)
        );
        directionalLight.setInfluencingBounds(new BoundingSphere(new Point3d(0, 0, 0), 100.0));
        lights.addChild(directionalLight);

        return lights;
    }

    private void setupCamera(BranchGroup root) {
        cameraTransformGroup = universe.getViewingPlatform().getViewPlatformTransform();
        cameraAngle = (float)  (Math.PI + Math.PI);  // 初始朝向
        updateCameraPosition();
    }

    private void updateCameraPosition() {
        Transform3D cameraTransform = new Transform3D();
        Point3d eye;
        Point3d center;

        if (isFirstPerson) {
            // 第一人称视角：相机位置与玩家位置绑定
            eye = new Point3d(playerX, 0.3f, playerZ);  // 模拟人眼高度
            center = new Point3d(
                    playerX + Math.sin(cameraAngle),
                    0.3f,  // 视线高度与相机一致
                    playerZ + Math.cos(cameraAngle)
            );
        } else {
            // 第三人称视角：使用独立的相机位置和固定的目标点
            eye = new Point3d(cameraX, cameraHeight, cameraZ);

            // 相机看向的目标点（稍微低于相机位置，形成俯视效果）
            center = new Point3d(
                    cameraX + Math.sin(cameraAngle),
                    cameraHeight - 2.0,  // 目标点比相机低2个单位
                    cameraZ + Math.cos(cameraAngle)
            );
        }

        Vector3d up = new Vector3d(0, 1, 0);
        cameraTransform.lookAt(eye, center, up);
        cameraTransform.invert();
        cameraTransformGroup.setTransform(cameraTransform);
    }

    private void handleKeyPress(KeyEvent e) {
        if (gameOver) return;

        float oldPlayerX = playerX;
        float oldPlayerZ = playerZ;

        // 处理视角切换
        if (e.getKeyCode() == KeyEvent.VK_Z && isFirstPerson) {
            // Z键：切换到第三人称
            isFirstPerson = false;
        } else if (e.getKeyCode() == KeyEvent.VK_X && !isFirstPerson) {
            // X键：切换回第一人称
            isFirstPerson = true;
        }

        // 移动和视角控制
        if (isFirstPerson) {
            // 第一人称
            switch (e.getKeyCode()) {
                case KeyEvent.VK_UP:    // 前进
                    playerX += playerSpeed * Math.sin(cameraAngle);
                    playerZ += playerSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_DOWN:  // 后退
                    playerX -= playerSpeed * Math.sin(cameraAngle);
                    playerZ -= playerSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_LEFT:  // 左移（同时左转）
                    playerX += playerSpeed * Math.cos(cameraAngle);
                    playerZ -= playerSpeed * Math.sin(cameraAngle);
                    cameraAngle += cameraturnSpeed;
                    break;
                case KeyEvent.VK_RIGHT: // 右移（同时右转）
                    playerX -= playerSpeed * Math.cos(cameraAngle);
                    playerZ += playerSpeed * Math.sin(cameraAngle);
                    cameraAngle -= cameraturnSpeed;
                    break;
            }
        } else {
            // 第三人称视角
            switch (e.getKeyCode()) {
                case KeyEvent.VK_UP:    // 前进
                    playerX += playerSpeed * Math.sin(cameraAngle);
                    playerZ += playerSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_DOWN:  // 后退
                    playerX -= playerSpeed * Math.sin(cameraAngle);
                    playerZ -= playerSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_LEFT:  // 左移
                    playerX += playerSpeed * Math.cos(cameraAngle);
                    playerZ -= playerSpeed * Math.sin(cameraAngle);
                    break;
                case KeyEvent.VK_RIGHT: // 右移
                    playerX -= playerSpeed * Math.cos(cameraAngle);
                    playerZ += playerSpeed * Math.sin(cameraAngle);
                    break;
                // 视角转向
                case KeyEvent.VK_A:     // 左转
                    cameraAngle += cameraturnSpeed;
                    break;
                case KeyEvent.VK_D:     // 右转
                    cameraAngle -= cameraturnSpeed;
                    break;
                case KeyEvent.VK_W: // 前进
                    cameraX += cameramoveSpeed * Math.sin(cameraAngle);
                    cameraZ += cameramoveSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_S: // 后退
                    cameraX -= cameramoveSpeed * Math.sin(cameraAngle);
                    cameraZ -= cameramoveSpeed * Math.cos(cameraAngle);
                    break;
                case KeyEvent.VK_E: // 降低高度
                    cameraHeight -= cameramoveSpeed;
                    if (cameraHeight < 1.0f) cameraHeight = 1.0f;
                    break;
                case KeyEvent.VK_Q: // 升高高度
                    cameraHeight += cameramoveSpeed;
                    break;
            }
        }

        // 碰撞检测
        if (isColliding()) {
            playerX = oldPlayerX;
            playerZ = oldPlayerZ;

            // 重新根据玩家位置设置相机位置（第一人称视角）
            if (isFirstPerson) {
                updateCameraPosition();
            }
        }

        // 更新玩家位置
        updatePlayerPosition();
        // 更新相机位置
        updateCameraPosition();

        // 终点检测逻辑
        float distanceToEnd = (float) Math.sqrt(
                Math.pow(playerX - endX, 2) + Math.pow(playerZ - endZ, 2)
        );
        if (distanceToEnd < endRadius) {
            gameOver = true;
            showSuccessMessage();
            startConfetti();
            startAnimationLoop();
            timer.cancel(); //成功就停止计时
        }

        // 检测是否拾取道具
        checkPowerUpCollision();
        // 更新道具状态
        updatePowerUpStatus();

    }


    // 检测玩家与道具的碰撞
    private void checkPowerUpCollision() {
        if (gameOver || isWallPassActive) return;

        for (PowerUp powerUp : powerUps) {
            if (powerUp.isActive()) {
                // 计算玩家与道具之间的距离
                float distance = (float)Math.sqrt(
                        Math.pow(playerX - powerUp.getX(), 2) +
                                Math.pow(playerZ - powerUp.getZ(), 2)
                );

                // 如果距离小于拾取范围，获取道具
                if (distance < (playerSize + 0.3f)) {
                    powerUp.activate();
                    // 根据道具类型激活效果
                    if (powerUp.getType() == Type.WALL_PASS) {
                        activateWallPass(powerUp.getDuration());
                    } else {
                        activateEnemyKiller(powerUp.getDuration()); // 激活杀敌效果
                    }
                    break;
                }
            }
        }
    }
    // 激活杀敌道具
    private void activateEnemyKiller(float duration) {
        isEnemyKillerActive = true;
        enemyKillerEndTime = System.currentTimeMillis() + (long)duration; // 用独立时间
        isEnemyKillerUsed = false; // 未过期，还没到“已使用”状态
        updatePowerUpDisplay();
        changePlayerColor(new Color3f(1.0f, 0.5f, 0.0f)); // 橙色
    }


    // 激活穿墙道具
    private void activateWallPass(float duration) {
        isWallPassActive = true;
        wallPassEndTime = System.currentTimeMillis() + (long)duration; // 用独立时间
        isWallPassUsed = false; // 未过期，还没到“已使用”状态
        updatePowerUpDisplay();
        changePlayerColor(new Color3f(0.2f, 1.0f, 0.2f)); // 绿色
    }

    // 更新道具状态显示
    private void updatePowerUpDisplay() {
        SwingUtilities.invokeLater(() -> {
            // 穿墙道具状态
            if (isWallPassActive) {
                long remaining = (wallPassEndTime - System.currentTimeMillis()) / 1000;
                powerUpLabel.setText("穿墙道具: " + remaining + "s");
            } else if (isWallPassUsed) {
                powerUpLabel.setText("穿墙道具: 已使用");
            } else {
                powerUpLabel.setText("穿墙道具: 未激活");
            }

            // 杀敌道具状态
            if (isEnemyKillerActive) {
                long remaining = (enemyKillerEndTime - System.currentTimeMillis()) / 1000;
                powerUpLabel2.setText("杀敌道具: " + remaining + "s");
            } else if (isEnemyKillerUsed) {
                powerUpLabel2.setText("杀敌道具: 已使用");
            } else {
                powerUpLabel2.setText("杀敌道具: 未激活");
            }
        });
    }

    // 改变玩家颜色
    private void changePlayerColor(Color3f color) {
        // 获取玩家的外观并改变颜色
        Node playerNode = playerTransformGroup.getChild(0);
        if (playerNode instanceof Sphere) {
            Sphere playerSphere = (Sphere)playerNode;
            Appearance app = playerSphere.getAppearance();
            Material mat = new Material(color, color, color, color, 80.0f);
            mat.setLightingEnable(true);
            app.setMaterial(mat);
        }
    }

    // 更新道具状态
    private void updatePowerUpStatus() {
        long currentTime = System.currentTimeMillis();

        // 穿墙道具过期检查
        if (isWallPassActive && currentTime > wallPassEndTime) {
            isWallPassActive = false;
            isWallPassUsed = true; // 标记为已使用
            changePlayerColor(new Color3f(0.2f, 0.2f, 1.0f)); // 恢复玩家颜色
            updatePowerUpDisplay();

            // 穿墙效果结束时检查是否在墙内，如果是则移动到最近的有效位置
            if (isPlayerInWall()) {
                movePlayerToNearestValidPosition();
            }
        }

        // 杀敌道具过期检查
        if (isEnemyKillerActive && currentTime > enemyKillerEndTime) {
            isEnemyKillerActive = false;
            isEnemyKillerUsed = true; // 标记为已使用
            changePlayerColor(new Color3f(0.2f, 0.2f, 1.0f)); // 恢复玩家颜色
            updatePowerUpDisplay();
        }
    }

    // 判断玩家是否处于墙内
    private boolean isPlayerInWall() {
        int cellX = Math.round(playerX);
        int cellZ = Math.round(playerZ);

        // 检查当前位置是否是墙
        if (cellX < 0 || cellX >= MAZE_SIZE || cellZ < 0 || cellZ >= MAZE_SIZE) {
            return true; // 超出边界视为在墙内
        }
        return maze[cellZ][cellX] == WALL;
    }

    // 将玩家移动到最近的有效位置
    private void movePlayerToNearestValidPosition() {
        // 搜索半径，从近到远寻找可通行位置
        float searchRadius = 0.5f;
        float step = 0.5f;
        int maxSearchSteps = 10; // 最大搜索步数，防止无限循环

        for (int stepCount = 0; stepCount < maxSearchSteps; stepCount++) {
            // 以玩家当前位置为中心，搜索正方形范围内的点
            for (float dx = -searchRadius; dx <= searchRadius; dx += step) {
                for (float dz = -searchRadius; dz <= searchRadius; dz += step) {
                    // 跳过中心位置（已经确认是墙）
                    if (Math.abs(dx) < 0.1f && Math.abs(dz) < 0.1f) {
                        continue;
                    }

                    float testX = playerX + dx;
                    float testZ = playerZ + dz;

                    // 检查该位置是否有效（不是墙且在迷宫内）
                    if (isPositionValid(testX, testZ)) {
                        // 找到有效位置，移动玩家
                        playerX = testX;
                        playerZ = testZ;
                        updatePlayerPosition();
                        updateCameraPosition();
                        return;
                    }
                }
            }
            // 扩大搜索范围
            searchRadius += step;
        }

        // 如果所有搜索都失败，将玩家移动到起点
        playerX = startX;
        playerZ = startZ;
        updatePlayerPosition();
        updateCameraPosition();
    }


    private void startConfetti() {
        // 获取彩带容器
        TransformGroup confettiContainer = (TransformGroup) confettiGroup.getChild(0);
        confettiContainer.removeAllChildren();

        // 添加所有彩带粒子
        for (Confetti particle : confettiParticles) {
            confettiContainer.addChild(particle.branchGroup);
        }
    }

    private boolean isColliding() {

        // 如果处于穿墙状态，允许穿过墙壁
        if (isWallPassActive) {
            // 仍然检查迷宫边界，不允许走出迷宫
            if (playerX < 0.5f || playerX >= MAZE_SIZE - 0.5f ||
                    playerZ < 0.5f || playerZ >= MAZE_SIZE - 0.5f) {
                return true;
            }
            return false; // 忽略墙壁碰撞
        }

        // 原有碰撞检测逻辑保持不变
        // 获取玩家所在单元格（中心位置）
        int cellX = Math.round(playerX);
        int cellZ = Math.round(playerZ);

        // 检查是否超出迷宫边界
        if (playerX < 0.5f || playerX >= MAZE_SIZE - 0.5f ||
                playerZ < 0.5f || playerZ >= MAZE_SIZE - 0.5f) {
            return true;
        }

        // 检查当前单元格是否是墙壁
        if (maze[cellZ][cellX] == WALL) {
            return true;
        }

        // 改进的碰撞检测
        float offset = 0.25f;

        // 检测玩家周围四个方向的近距离单元格
        int[][] checkDirections = {
                {(int)Math.round(playerX - offset), (int)Math.round(playerZ)},  // 左
                {(int)Math.round(playerX + offset), (int)Math.round(playerZ)},  // 右
                {(int)Math.round(playerX), (int)Math.round(playerZ - offset)},  // 前
                {(int)Math.round(playerX), (int)Math.round(playerZ + offset)}   // 后
        };

        for (int[] dir : checkDirections) {
            int cx = dir[0];
            int cz = dir[1];

            if (cx >= 0 && cx < MAZE_SIZE && cz >= 0 && cz < MAZE_SIZE) {
                if (maze[cz][cx] == WALL) {
                    return true;
                }
            }
        }

        return false;
    }


    private BranchGroup createSuccessMessage() {
        BranchGroup messageGroup = new BranchGroup();
        messageGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);

        Text2D text = new Text2D("闯关成功!", new Color3f(1.0f, 1.0f, 0.0f),
                "Arial", 36, Font.BOLD);
        text.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);

        Appearance app = text.getAppearance();
        ColoringAttributes ca = new ColoringAttributes(new Color3f(1.0f, 1.0f, 0.0f), ColoringAttributes.SHADE_FLAT);
        app.setColoringAttributes(ca);
        text.setAppearance(app);
        text.setName("successText");

        Transform3D transform = new Transform3D();
        transform.setTranslation(new Vector3f(MAZE_SIZE/2 - 2, 2.0f, MAZE_SIZE/2));
        TransformGroup textGroup = new TransformGroup(transform);
        textGroup.addChild(text);
        messageGroup.addChild(textGroup);

        return messageGroup;
    }

    private void startAnimationLoop() {
        new Thread(() -> {
            while (gameOver) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (Confetti c : confettiParticles) {
                    c.update();
                }
            }
        }).start();
    }
}